﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AviumX.AviumCore.System.Terminal
{
    class TerminalHandle
    {
        //Terminal Class - Toxickill

        //Controls back color.
        public AviumX.AviumCore.Screen.ScreenX.SystemColors BackColor = AviumX.AviumCore.Screen.ScreenX.SystemColors.Yellow;
        public bool Enabled = true;
        //Controls font.
        public AviumCore.Screen.Graphics.Fonts.Font.Fonts Font = AviumCore.Screen.Graphics.Fonts.Font.Fonts.EnvySys;
        //Controls fore color.
        public AviumX.AviumCore.Screen.ScreenX.SystemColors ForeColor = AviumX.AviumCore.Screen.ScreenX.SystemColors.White;
        //Controls border color.
        public AviumX.AviumCore.Screen.ScreenX.SystemColors BorderColor = AviumX.AviumCore.Screen.ScreenX.SystemColors.White;
        bool Password = false;
        //Controls location.
        public AviumCore.Screen.Graphics.Vector Position = new AviumCore.Screen.Graphics.Vector(0, 0);
        //Controls dementions.
        public uint Width = 58;
        public uint Height = 10;
        //Simple accessable holders for the current line
        public int CurrentLine = 0;
        public int MaxLine = 0;
        public int MinLine = 0;
        private int CurrentY;
        //Simple private holder for the text in individual lines
        private string[] TextSplit;
        //Controls text.
        public string Text = "Terminal";
        //A simple undo buffer
        private string TextCleared = "";
        //Controls parent.
        public AviumCore.WinAPI.Window ParentWindow;
        public bool TestOverride = false;
        //Is the control currently selected.
        bool InFocus = false;
        string key = "";
        int StringCapacity = 0;
        int LettersToPrint = 0;
        public void Draw(AviumX.AviumCore.WinAPI.Window parent)
        {
            // Split the text into a holder at each new line
            TextSplit = Text.Split('\n');
            // Work out which line to start printing from
            if (MaxLine * 8 > (int)Height)
            {
                MinLine = MaxLine - ((int)Height / 8);
            }
            else
            {
                MinLine = 0;
            }
            // Declare the ParentWindow as the variable specified when the method is called (probably by ZCode)
            ParentWindow = parent;
            // Draw a solid rectangle behind which will become the border when a new rectangle is written over it.
            AviumCore.Screen.Graphics.Drawing.DrawRectangle(Position, Width, Height, BorderColor);
            if (InFocus == true)
            {
                AviumCore.Screen.Graphics.Drawing.DrawRectangle((uint)Position.x + 1, (uint)Position.y + 1, Width - 2, Height - 2, BackColor);
            }
            else
            {
                AviumCore.Screen.Graphics.Drawing.DrawRectangle((uint)Position.x + 1, (uint)Position.y + 1, Width - 2, Height - 2, AviumCore.Screen.ScreenX.SystemColors.Gray);
            }


            if (InFocus == true)
            {
                for (int i = MinLine; i < MaxLine; i++)
                {
                    AviumCore.Screen.Graphics.Fonts.FontHandle.Print(Font, ForeColor, TextSplit[i], Position.x + 1, CurrentY);
                    CurrentY += 8;
                }
            }
            else
            {
                for (int i = MinLine; i < MaxLine; i++)
                {
                    AviumCore.Screen.Graphics.Fonts.FontHandle.Print(Font, AviumCore.Screen.ScreenX.SystemColors.DarkGray, TextSplit[i], Position.x + 1, CurrentY);
                    CurrentY += 8;
                }
            }
            /*
               * If its parent is infront then we can handle mouse click ect.. if not then we dont
               * handle or check for mouse clicks, either way the control still gets drawn.
               */

            if (ParentWindow.infront == true)
            {
                CheckClicks();
                CheckHover();
                if (InFocus == true)
                {
                    Update();
                }
            }
            else
            {
                /*
                 * The parent is not infront so lets reset this textbox to not be clicked on.
                 */
                InFocus = false;
            }
            // Resets the current y coordinate to make sure everything prints properly next time
            CurrentY = 0;
            #region Reconstruct the string - I will improve this at a later date (it requires lots of editing code) but for now it is the best method
            Text = "";
            for (int i = 0; i < MaxLine; i++)
            {
                Text += TextSplit[i];
            }
            #endregion
        }
        public void Update()
        {
            /*
             * Check the keyboard for keypresses.
             */
            int LineLength = TextSplit[CurrentLine].Length * 8;

            key = Hardware.Keyboard.KeyBoardCreated.TheKeyBoard.Key;
            if (key == "DEL")
            {
                if (Text.Length > 0)
                {
                    TextSplit[CurrentLine] = TextSplit[CurrentLine].Substring(0, TextSplit[CurrentLine].Length - 1);
                }
                if (TextSplit[CurrentLine].Length == 0)
                {
                    CurrentLine -= 1;
                }
                Hardware.Keyboard.KeyBoardCreated.TheKeyBoard.ClearUpdate();
            }
            else if (key == "DOWN")
            {
                CurrentLine += 1;
                Hardware.Keyboard.KeyBoardCreated.TheKeyBoard.ClearUpdate();
            }
            else if (key == "UP")
            {
                CurrentLine -= 1;
                Hardware.Keyboard.KeyBoardCreated.TheKeyBoard.ClearUpdate();
            }
            else if (key == "")
            {
                Hardware.Keyboard.KeyBoardCreated.TheKeyBoard.ClearUpdate();
            }
            else if (Hardware.Keyboard.KeyBoardCreated.TheKeyBoard.ShiftKey() == 1)
            {
                if (LineLength > Width)
                {
                    CurrentLine += 1;
                    TextSplit[CurrentLine] += '\n';
                }
                TextSplit[CurrentLine] += key.ToUpper();
                Hardware.Keyboard.KeyBoardCreated.TheKeyBoard.ClearUpdate();
            }
            else if (key == "ENTER")
            {
                CurrentLine = CurrentLine + 1;
                
                TextSplit[CurrentLine] += '\n';
                Hardware.Keyboard.KeyBoardCreated.TheKeyBoard.ClearUpdate();
            }
            else
            {
                if (LineLength > Width)
                {
                    CurrentLine += 1;
                }
                TextSplit[CurrentLine] += key;
                Hardware.Keyboard.KeyBoardCreated.TheKeyBoard.ClearUpdate();
            }
            MaxLine = CurrentLine;
        }
        private void CheckClicks()
        {
            /*
             * This handles the click event for this control.
             */
            if (ParentWindow.infront == true || TestOverride == true)
            {
                if (Hardware.Mouse.Cursor.CheckMouseLeftClick(Position.x, Position.y, (int)Width, (int)Height) == true)
                {
                    InFocus = true;
                }
                else
                {
                    if (Hardware.Mouse.Cursor.Mouse.TheMouse.Buttons == Cosmos.Hardware.Mouse.MouseState.Left)
                    {
                        InFocus = false;
                    }
                }
            }
        }
        private void CheckHover()
        {
            if (ParentWindow.infront == true)
            {
                if (Hardware.Mouse.Cursor.Mouse.Getx() > Position.x && Hardware.Mouse.Cursor.Mouse.Getx() < (Position.x + Width) && Hardware.Mouse.Cursor.Mouse.Gety() > Position.y && Hardware.Mouse.Cursor.Mouse.Gety() < (Position.y + Height))
                {
                    Hardware.Mouse.Cursor.CurrentCursor = AviumX.AviumCore.Hardware.Mouse.Cursor.CursorType.IBeam;
                }
            }
            else
            {
                AviumX.AviumCore.Hardware.Mouse.Cursor.CurrentCursor = AviumX.AviumCore.Hardware.Mouse.Cursor.CursorType.Standard;
            }
        }
        #region These bits from the normal textbox work perfectly, please do not edit until this comment/region is removed thanks, Toxickill
        public void TryUpdate(WinAPI.Window parent)
        {
            this.ParentWindow = parent;
            if (ParentWindow.infront == true)
            {
                CheckClicks();
                CheckHover();
                if (InFocus == true)
                {
                    Update();
                }
            }
            else
            {
                /*
                 * The parent is not infront so lets reset this textbox to not be clicked on.
                 */
                InFocus = false;
            }
        }
        public void Clear()
        {
            TextCleared = Text;
            Text = "";
        }
        public void AppendText(string text)
        {
            Text = Text + text;
        }
        public void UndoClear()
        {
            Text = TextCleared;
            TextCleared = "";
        }
        public void CopyAll()
        {
            WinAPI.ClipBoard.ChangeContent(Text);
        }
        public void Paste()
        {
            AppendText(WinAPI.ClipBoard.GetContent());
        }
        public void CutAll()
        {
            WinAPI.ClipBoard.ChangeContent(Text);
            Clear();
        }
        public void Equals(string text)
        {
            Text = text;
        }
        #endregion

    }
}
